package com.jt.spring.demo2.aop;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

//AOP 面向切面编程
//知识铺垫：切面=动态代理+方法的扩展 后期AOP API封装
//切入点表达式：为谁创建代理对象

@Component//将这个类交给spring容器管理
@Aspect//标识当前类是一个切面
public class TxAspect {
    //编码：切面=切入点表达式+通知方法
    //@Pointcut("bean(userServiceImpl)")
    @Pointcut("within(com.jt.spring.demo2.service.*)")
    //@Pointcut("execution(void com.jt.spring.demo2.service.UserServiceImpl.addUser())")
   //  @Pointcut("execution(返回值类型 包名、类名、方法名（参数列表)")

    public void pointCut(){

    }
    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        //1,获取目标对象的类型
        Class targetClass = joinPoint.getTarget().getClass();
        //2,获取目标对象的名称
        String targetName = joinPoint.getSignature().getDeclaringTypeName();
        //3,获取目标方法的名称
        String methodname = joinPoint.getSignature().getName();
        //4,获取参数数据
        Object[]args=joinPoint.getArgs();
        System.out.println("目标对象的类型:"+targetClass);
        System.out.println("目标对象的名称:"+targetName);
        System.out.println("目标方法的名称:"+methodname );
        System.out.println("参数名称:"+ Arrays.toString(args));
        System.out.println("AOP前置通知");
    }


    @AfterReturning(value = "pointCut()",returning = "result")
    public void afterReturning(Object result){
        System.out.println("方法的返回值:"+result);


    }
    @AfterThrowing(value = "pointCut()",throwing = "exception")
    public void AfterThrowing(Exception exception){
        exception.printStackTrace();
        System.out.println("异常信息"+exception.getMessage());
    }

    @After("pointCut()")
    public void after(){
        System.out.println("我是最终通知");
    }

    /*环绕通知中必须添加参数,并且必须位于第一位
    *
    * 用法:
    * 1,如果有下一个通知,则执行下一个通知,
    * 2,如果没有下一个通知则执行目标方法
    *
    * */

    /*
    *1, proceedingJoinPoint 只使用于环绕通知,因为只有环绕通知才能控制*/
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知开始");
        Object result=joinPoint.proceed();//proceed():调用目标方法
        System.out.println("环绕通知结束");
        return result;

    }

}
